home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Programming / DiceSource / src / dutil / libmake.c < prev    next >
C/C++ Source or Header  |  1997-09-09  |  12KB  |  652 lines

  1. /*
  2.  *    (c)Copyright 1992-1997 Obvious Implementations Corp.  Redistribution and
  3.  *    use is allowed under the terms of the DICE-LICENSE FILE,
  4.  *    DICE-LICENSE.TXT.
  5.  */
  6.  
  7. /*
  8.  *  libmake.c
  9.  *
  10.  *  libmake  -n -oobjdir -l library file [-clean] [-pr] [-mr/R] [-proto] -Ddefine
  11.  *        -prof
  12.  *
  13.  *  loads 'files' list and compiles out of date files accordingly, putting
  14.  *  objects in an alternate directory if requested.
  15.  *
  16.  *  if -pr is specified it will be passed on to the compiler
  17.  */
  18.  
  19. #include <exec/types.h>
  20. #include <exec/nodes.h>
  21. #include <exec/lists.h>
  22. #include <libraries/dos.h>
  23. #define abs
  24. #include <clib/dos_protos.h>
  25. #include <clib/exec_protos.h>
  26. #include <clib/alib_protos.h>
  27. #include <lists.h>
  28. #include <stdio.h>
  29. #include <stdlib.h>
  30. #include <string.h>
  31. #include <lib/misc.h>
  32. #include <lib/version.h>
  33.  
  34. #define EF_OOD        0x01
  35. #define EF_COMP     0x02
  36. #define EF_NOJOIN   0x04
  37.  
  38. typedef struct {
  39.     char *SrcName;
  40.     char *ObjName;
  41.     long Flags;
  42. } NameNode;
  43.  
  44. typedef struct Node Node;
  45. typedef struct List List;
  46. typedef struct MinNode MinNode;
  47. typedef struct MinList MinList;
  48.  
  49. typedef struct DateStamp DateStamp;
  50.  
  51. char Prefix[64];
  52. char *CtlFile;
  53. char *ObjDir;
  54. char *DestLib;
  55. NameNode *NList;
  56. short    NumFiles;
  57. short    DccExec;
  58. short    DryRun;
  59. short    Verbose;
  60. short    Broke;
  61. short    Clean;
  62. short    PROpt;
  63. short    ProtoOpt;
  64. short    RegCallOpt;
  65. short    LargeDataOpt;
  66. short    LargeCodeOpt;
  67. short    ProfOpt;
  68. List    DefList;
  69. List    ComFileList;
  70. static char Buf[256];
  71.  
  72. int brk(void);
  73. int main(int, char **);
  74. void help(int);
  75. int TimeCompareFiles(void);
  76. int CompileFiles(void);
  77. int Assemble(char *, char *);
  78. int AssembleA68K(char *, char *);
  79. int Compile(char *, char *);
  80. int CompareTimes(DateStamp *, DateStamp *);
  81. int ALibMake(void);
  82. char *MungeFile(char *, char *);
  83. char *GetIndex(char **);
  84. int run_cmd(char *, int);
  85. int GetFileTime(char *, DateStamp *);
  86. Node *MakeNode(const char *);
  87.  
  88. #ifdef LATTICE
  89. MinNode *GetHead(MinList *);
  90. MinNode *GetSucc(MinNode *);
  91. #endif
  92.  
  93. int
  94. brk()
  95. {
  96.     Broke = 1;
  97.     return(0);
  98. }
  99.  
  100. main(ac, av)
  101. int ac;
  102. char *av[];
  103. {
  104.     char *nameBuf;
  105.  
  106.     onbreak(brk);
  107.  
  108.  
  109.     NewList(&DefList);
  110.     NewList(&ComFileList);
  111.  
  112.     /*
  113.      *    calculate prefix
  114.      */
  115.  
  116. #ifdef _DCC
  117.     DccExec = 1;
  118. #else
  119.     DccExec = 0;
  120. #endif
  121.  
  122.     {
  123.     char *ptr = av[0];
  124.     short len = strlen(ptr);
  125.  
  126.     while (len >= 0 && ptr[len] != '/' && ptr[len] != ':')
  127.         --len;
  128.     ptr = ptr + len + 1;    /*  file part    */
  129.  
  130.     for (len = 0; ptr[len] && ptr[len] != '_'; ++len);
  131.     if (ptr[len] == '_')
  132.         ++len;
  133.     else
  134.         len = 0;
  135.     strncpy(Prefix, ptr, len);
  136.     Prefix[len] = 0;
  137.     }
  138.     {
  139.     short i;
  140.  
  141.     for (i = 1; i < ac; ++i) {
  142.         char *ptr = av[i];
  143.         if (*ptr != '-') {
  144.         if (CtlFile == NULL) {
  145.             CtlFile = ptr;
  146.             continue;
  147.         }
  148.         AddTail(&ComFileList, MakeNode(ptr));
  149.         continue;
  150.         }
  151.         ptr += 2;
  152.         switch(ptr[-1]) {
  153.         case 'v':
  154.         Verbose = 1;
  155.         break;
  156.         case 'n':
  157.         DryRun = 1;
  158.         break;
  159.         case 'D':
  160.         if (*ptr == 0)
  161.             ptr = av[++i];
  162.         AddTail(&DefList, MakeNode(ptr));
  163.         break;
  164.         case 'o':
  165.         if (*ptr)
  166.             ObjDir = ptr;
  167.         else
  168.             ObjDir = av[++i];
  169.         break;
  170.         case 'l':
  171.         if (*ptr)
  172.             DestLib = ptr;
  173.         else
  174.             DestLib = av[++i];
  175.         break;
  176.         case 'c':
  177.         Clean = 1;
  178.         DestLib = "";
  179.         break;
  180.         case 'p':
  181.         if (strcmp(ptr, "rof") == 0)
  182.             ProfOpt = 1;
  183.         else if (strcmp(ptr, "r") == 0)
  184.             PROpt = 1;
  185.         else if (strcmp(ptr, "roto") == 0)
  186.             ProtoOpt = 1;
  187.         else
  188.             help(1);
  189.         break;
  190.         case 'm':
  191.         switch(*ptr) {
  192.         case 'r':
  193.             RegCallOpt = 1;
  194.             break;
  195.         case 'R':
  196.             RegCallOpt = 2;
  197.             if (ptr[1] == 'R')
  198.             RegCallOpt = 3;
  199.             break;
  200.         case 'D':
  201.             LargeDataOpt = 1;
  202.             break;
  203.         case 'C':
  204.             LargeCodeOpt = 1;
  205.             break;
  206.         }
  207.         break;
  208.         default:
  209.         help(1);
  210.         }
  211.     }
  212.     if (i > ac)
  213.         help(1);
  214.     }
  215.     if (ObjDir == NULL) {
  216.     puts("must specify an output directory for objects (-o)");
  217.     exit(1);
  218.     }
  219.     if (DestLib == NULL) {
  220.     puts("must specify output library (-l)");
  221.     exit(1);
  222.     }
  223.     {
  224.     FILE *fi = fopen(CtlFile, "r");
  225.     long siz;
  226.  
  227.     if (fi == NULL) {
  228.         perror("fopen");
  229.         exit(1);
  230.     }
  231.     fseek(fi, 0L, 2);
  232.     siz = ftell(fi);
  233.     if (siz < 0) {
  234.         perror("fseek");
  235.         exit(1);
  236.     }
  237.     fseek(fi, 0L, 0);
  238.     nameBuf = malloc(siz + 1);
  239.     if (fread(nameBuf, siz, 1, fi) != 1) {
  240.         perror("fread");
  241.         exit(1);
  242.     }
  243.     fclose(fi);
  244.     nameBuf[siz] = 0;
  245.     }
  246.     {
  247.     char *namePtr;
  248.     char *getIdx;
  249.     long files = 0;
  250.     NameNode *nn;
  251.  
  252.     getIdx = nameBuf;
  253.  
  254.     for (namePtr = GetIndex(&getIdx); *namePtr; namePtr = GetIndex(&getIdx))
  255.         ++files;
  256.     {
  257.         Node *node;
  258.         for (node = GetHead(&ComFileList); node; node = GetSucc(node))
  259.         ++files;
  260.     }
  261.     NList = malloc(sizeof(NameNode) * files);
  262.  
  263.     nn = NList;
  264.  
  265.     getIdx = nameBuf;
  266.     NumFiles = 0;
  267.     for (namePtr = GetIndex(&getIdx); *namePtr; namePtr = GetIndex(&getIdx)) {
  268.         if (*namePtr == ';')
  269.         continue;
  270.         nn->Flags = 0;
  271.         if (namePtr[0] == '*') {
  272.         nn->Flags |= EF_NOJOIN;
  273.         ++namePtr;
  274.         }
  275.         nn->SrcName = namePtr;
  276.         nn->ObjName = MungeFile(nn->SrcName, ObjDir);
  277.         ++nn;
  278.         ++NumFiles;
  279.     }
  280.     {
  281.         Node *node;
  282.         for (node = GetHead(&ComFileList); node; node = GetSucc(node)) {
  283.         nn->Flags = 0;
  284.         if (node->ln_Name[0] == '*') {
  285.             nn->Flags |= EF_NOJOIN;
  286.             ++node->ln_Name;
  287.         }
  288.         nn->SrcName = node->ln_Name;
  289.         nn->ObjName = MungeFile(node->ln_Name, ObjDir);
  290.         ++nn;
  291.         ++NumFiles;
  292.         }
  293.     }
  294.     }
  295.  
  296.     if (Clean) {
  297.     NameNode *nn;
  298.     short i;
  299.  
  300.     for (i = 0, nn = NList; i < NumFiles; ++i, ++nn) {
  301.         if (strcmp(nn->SrcName, nn->ObjName) != 0) {
  302.         printf("%s\n", nn->ObjName);
  303.         remove(nn->ObjName);
  304.         }
  305.     }
  306.     } else {
  307.     if (TimeCompareFiles() < 0) {
  308.         if (CompileFiles() != 0)
  309.         exit(10);
  310.         if (ALibMake() < 0)
  311.         exit(20);
  312.     }
  313.     }
  314.     return(0);
  315. }
  316.  
  317. void
  318. help(n)
  319. {
  320.     fprintf(stderr, "libmake [-n] files -o objdir/ -l library [-clean]\n");
  321.     exit(n);
  322. }
  323.  
  324. int
  325. TimeCompareFiles()
  326. {
  327.     NameNode *nn;
  328.     short i;
  329.     short r = 0;
  330.     DateStamp d1;
  331.     DateStamp d2;
  332.     DateStamp d3;
  333.  
  334.     if (GetFileTime(DestLib, &d3) < 0)
  335.     r = -1;
  336.  
  337.     for (i = 0, nn = NList; i < NumFiles; ++i, ++nn) {
  338.     /*
  339.      *  ignore files that are just being inserted
  340.      */
  341.  
  342.     if (strcmp(nn->SrcName, nn->ObjName) == 0)
  343.         continue;
  344.  
  345.     /*
  346.      *  compare files that may need compilation, source against
  347.      *  object and object against destination
  348.      */
  349.  
  350.     if (GetFileTime(nn->SrcName, &d1)) {
  351.         fprintf(stderr, "unable to find %s\n", nn->SrcName);
  352.         continue;
  353.     }
  354.     if (GetFileTime(nn->ObjName, &d2) == 0) {
  355.         if (CompareTimes(&d3, &d2) < 0)
  356.         r = -1;
  357.         if (CompareTimes(&d1, &d2) < 0)
  358.         continue;
  359.     }
  360.     nn->Flags |= EF_OOD;
  361.     r = -1;
  362.     }
  363.     return(r);
  364. }
  365.  
  366. int
  367. CompareTimes(d1, d2)
  368. DateStamp *d1;
  369. DateStamp *d2;
  370. {
  371.     if (d1->ds_Days < d2->ds_Days)
  372.     return(-1);
  373.     if (d1->ds_Days == d2->ds_Days) {
  374.     if (d1->ds_Minute < d2->ds_Minute)
  375.         return(-1);
  376.     if (d1->ds_Minute == d2->ds_Minute) {
  377.         if (d1->ds_Tick < d2->ds_Tick)
  378.         return(-1);
  379.         if (d1->ds_Tick == d2->ds_Tick)
  380.         return(0);
  381.     }
  382.     }
  383.     return(1);
  384. }
  385.  
  386.  
  387. CompileFiles()
  388. {
  389.     NameNode *nn;
  390.     short i;
  391.     int errs = 0;
  392.  
  393.     for (i = 0, nn = NList; i < NumFiles; ++i, ++nn) {
  394.     if (nn->Flags & EF_OOD) {
  395.         short j;
  396.         char *ptr;
  397.  
  398.         if (strcmp(nn->SrcName, nn->ObjName) != 0) {
  399.         for (j = strlen(nn->SrcName) - 1; j >= 0 && nn->SrcName[j] != '.'; --j);
  400.         if (++j == 0)
  401.             ptr = "";
  402.         else
  403.             ptr = nn->SrcName + j;
  404.  
  405.         if (stricmp(ptr, "a") == 0 || stricmp(ptr, "asm") == 0) {
  406.             errs += Assemble(nn->SrcName, nn->ObjName);
  407.         } else if (stricmp(ptr, "a68") == 0) {
  408.             errs += AssembleA68K(nn->SrcName, nn->ObjName);
  409.         } else {
  410.             errs += Compile(nn->SrcName, nn->ObjName);
  411.         }
  412.         }
  413.     }
  414.     }
  415.     return(errs);
  416. }
  417.  
  418. Assemble(src, obj)
  419. char *src;
  420. char *obj;
  421. {
  422.     sprintf(Buf, "%sdas -o%s %s", Prefix, obj, src);
  423.     return(run_cmd(Buf, DccExec));
  424. }
  425.  
  426. AssembleA68K(src, obj)
  427. char *src;
  428. char *obj;
  429. {
  430.     sprintf(Buf, "a68k -o%s %s -q", obj, src);
  431.     return(run_cmd(Buf, 0));
  432. }
  433.  
  434. /*
  435.  *  COMPILE:
  436.  *    -r  make residentable code
  437.  *    -ms put const objects, including string constants, in the code segment
  438.  */
  439.  
  440. Compile(src, obj)
  441. char *src;
  442. char *obj;
  443. {
  444.     char *verb = (Verbose) ? "-v" : "";
  445.     char *propt= (PROpt) ? " -pr" : "";
  446.     char *proto= (ProtoOpt) ? " -proto" : "";
  447.     char *prof = (ProfOpt) ? " -prof" : "";
  448.     char *rco;
  449.     char *ldata= (LargeDataOpt) ? " -mD" : "";
  450.     char *lcode= (LargeCodeOpt) ? " -mC" : "";
  451.  
  452.     switch(RegCallOpt) {
  453.     case 0:
  454.     rco = "";
  455.     break;
  456.     case 1:
  457.     rco = " -mr";
  458.     break;
  459.     case 2:
  460.     rco = " -mR";
  461.     break;
  462.     case 3:
  463.     rco = " -mRR";
  464.     break;
  465.     }
  466.  
  467.     sprintf(Buf, "%sdcc -c %s -o %s %s -S -r -ms%s%s%s%s%s%s",
  468.     Prefix, src, obj, verb, propt, rco, proto, prof, ldata, lcode
  469.     );
  470.     {
  471.     Node *node;
  472.     short len = strlen(Buf);
  473.     for (node = GetHead(&DefList); node; node = GetSucc(node)) {
  474.         len += sprintf(Buf + len, " -D%s", node->ln_Name);
  475.     }
  476.     }
  477.     return(run_cmd(Buf, DccExec));
  478. }
  479.  
  480. ALibMake()
  481. {
  482.     NameNode *nn;
  483.     short i;
  484.     int r = -1;
  485.     FILE *fo;
  486.  
  487.     if (DryRun)
  488.     return(0);
  489.  
  490.     printf("Creating alink 'join' type libray %s\n", DestLib);
  491.     if (fo = fopen(DestLib, "w")) {
  492.     r = 0;
  493.     for (i = 0, nn = NList; i < NumFiles; ++i, ++nn) {
  494.         FILE *fi;
  495.         if (nn->Flags & EF_NOJOIN)
  496.         continue;
  497.         if (fi = fopen(nn->ObjName, "r")) {
  498.         int c;
  499.         while ((c = getc(fi)) != EOF)
  500.             putc(c, fo);
  501.         fclose(fi);
  502.         } else {
  503.         printf("Couldn't read %s\n", nn->ObjName);
  504.         r = -1;
  505.         }
  506.     }
  507.     fclose(fo);
  508.     } else {
  509.     printf("Unable to create %s\n", DestLib);
  510.     }
  511.     return(r);
  512. }
  513.  
  514.  
  515.  
  516. char *
  517. MungeFile(name, prefix)
  518. char *name;
  519. char *prefix;
  520. {
  521.     char *str;
  522.     char *postfix = ".o";
  523.     short i;
  524.  
  525.     for (i = strlen(name) - 1; i >= 0 && name[i] != '.'; --i);
  526.     if (i < 0)
  527.     i = strlen(name);
  528.  
  529.     if (stricmp(name + i, ".o") == 0 || stricmp(name + i, ".lib") == 0) {
  530.     str = malloc(strlen(name) + 1);
  531.     strcpy(str, name);
  532.     } else {
  533.     str = malloc(strlen(prefix) + i + strlen(postfix) + 1);
  534.     strcpy(str, prefix);
  535.     sprintf(str + strlen(str), "%.*s%s", (long)i, name, postfix);
  536.     }
  537.     return(str);
  538. }
  539.  
  540. char *
  541. GetIndex(ip)
  542. char **ip;
  543. {
  544.     char *ptr = *ip;
  545.     char *rp;
  546.  
  547.     while (*ptr == ' ' || *ptr == '\t' || *ptr == '\n')
  548.     ++ptr;
  549.     if (*ptr == 0)
  550.     return(ptr);
  551.     rp = ptr;
  552.     while (*ptr && *ptr != '\n')
  553.     ++ptr;
  554.     *ptr = 0;
  555.     *ip = ptr + 1;
  556.     return(rp);
  557. }
  558.  
  559. run_cmd(buf, dccExec)
  560. char *buf;
  561. {
  562.     printf("%s\n", buf);
  563.     if (Broke) {
  564.     printf("^C\n");
  565.     exit(1);
  566.     }
  567.     if (DryRun)
  568.     return(0);
  569.  
  570. #ifdef _DCC
  571.     if (dccExec) {
  572.     short i;
  573.     long r;
  574.  
  575.     for (i = 0; buf[i] && buf[i] != ' '; ++i);
  576.     if (buf[i] == ' ') {
  577.         buf[i] = 0;
  578.         for (++i; buf[i] == ' '; ++i);
  579.     }
  580.     r = exec_dcc(buf, buf + i);
  581.     if (r) {
  582.         printf("Exit code %d\n", r);
  583.         exit(1);
  584.     }
  585.     return(r);
  586.     }
  587. #endif
  588.  
  589.     Execute(buf, NULL, Output());
  590.     return(0);
  591. }
  592.  
  593. GetFileTime(file, ds)
  594. char *file;
  595. DateStamp *ds;
  596. {
  597.     static struct FileInfoBlock *Fib;
  598.     long rv = -1;
  599.     BPTR lock;
  600.  
  601.     if (Fib == NULL)
  602.     Fib = malloc(sizeof(struct FileInfoBlock));
  603.     if (lock = Lock(file, SHARED_LOCK)) {
  604.     if (Examine(lock, Fib)) {
  605.         *ds = Fib->fib_Date;
  606.         rv = 0;
  607.     }
  608.     UnLock(lock);
  609.     }
  610.     return(rv);
  611. }
  612.  
  613. Node *
  614. MakeNode(str)
  615. const char *str;
  616. {
  617.     Node *node = malloc(sizeof(Node) + strlen(str) + 1);
  618.     node->ln_Name = (char *)(node + 1);
  619.     strcpy(node->ln_Name, str);
  620.     return(node);
  621. }
  622.  
  623. #ifdef LATTICE
  624.  
  625. /*
  626.  *  required since this program needs to be used by the bootstrap compile,
  627.  *  before DICE's c.lib exists.
  628.  */
  629.  
  630. MinNode *
  631. GetHead(list)
  632. MinList *list;
  633. {
  634.     MinNode *node;
  635.     node = list->mlh_Head;
  636.     if (node->mln_Succ)
  637.     return(node);
  638.     return(NULL);
  639. }
  640.  
  641. MinNode *
  642. GetSucc(node)
  643. MinNode *node;
  644. {
  645.     node = node->mln_Succ;
  646.     if (node->mln_Succ)
  647.     return(node);
  648.     return(NULL);
  649. }
  650.  
  651. #endif
  652.